package com.lagou.gateway.util.jwt;

import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException;
import com.sun.org.apache.xml.internal.security.utils.Base64;
import io.jsonwebtoken.*;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class JJwtTool {
    private static String SECRET = "https://doooyo.github.io";

    // 1小时过期
    public static final int calendarField = Calendar.HOUR_OF_DAY;
    public static final int calendarInterval = 1;

    /**
     * 通过JJWT生成
     *
     * @param uid     用户ID作为jwt ID
     * @param subject 主题
     * @return
     */
    public static String generateJwt(String uid, String subject) {
        // 指定签名算法，支持哪些请自行查阅
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

        // 过期时间1小时
        Calendar nowTime = Calendar.getInstance();
        nowTime.add(calendarField, calendarInterval);
        Date expiresDate = nowTime.getTime();

        /*
         * 秘钥也可以根据规则生成，这里就使用上面写死的字符串
         * 方法支持接收 SecretKey对象 或 String字符串
         */
        // SecretKey SECRET = generalKey();

        // header Map
        Map<String, Object> header = new HashMap<>();
        header.put("alg", "HS256");
        header.put("typ", "JWT");

        // Playload负载的信息最终都是放到Claims
        Claims claims = Jwts.claims();
        // 自定义字段
        claims.put("name", "lee");

        // 官方定义字段
        claims.setId(uid);             // 编号(这里使用用户ID)
        claims.setAudience("all");     // 受众
        claims.setIssuer("lee");      // 签发者
        claims.setIssuedAt(new Date());// 签发时间
        claims.setSubject(subject);    // 主题
        claims.setNotBefore(new Date());   // 生效时间
        //claims.setExpiration(expiresDate); // 过期时间，也可以写在下面builder

        JwtBuilder builder = Jwts.builder()
                .setHeader(header)
                .setClaims(claims)            // 也支持Map
                .setExpiration(expiresDate)   // 在claims设置也可以
                .signWith(signatureAlgorithm, SECRET); // 签名算法以及密匙
        return builder.compact();
    }


    /**
     * 通过JJWT解析
     *
     * @param token 即jwt
     * @return
     * @throws Exception
     */
    public static Claims parseJwtToken(String token) {
        //SecretKey secretKey = generalKey();
        Jws<Claims> jws = Jwts.parser()
                .setSigningKey(SECRET)
                .parseClaimsJws(token);

        String signature = jws.getSignature();        // 签名部分
        Map<String, String> header = jws.getHeader(); // 头部
        Claims claims = jws.getBody();                // Payload负载部分

        return claims;
    }

    public static Claims verify(String token, String issuer) {
        Jws<Claims> jws = Jwts.parser()
                .setSigningKey(SECRET)
                .requireIssuer(issuer)
                .parseClaimsJws(token);

        String signature = jws.getSignature();        // 签名部分
        Map<String, String> header = jws.getHeader(); // 头部
        Claims claims = jws.getBody();                // Payload负载部分

        Date expiresAt = claims.getExpiration();

        return expiresAt.after(new Date()) ? claims : null;
    }

    public static SecretKey generalKey() {
        byte[] encodedKey = new byte[0];
        try {
            encodedKey = Base64.decode(SECRET);
        } catch (Base64DecodingException e) {
            e.printStackTrace();
        }
        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
        return key;
    }
}